import java.util.Random;
import java.util.concurrent.*;

/**
 * Created by Administrator on 2016/4/5.
 */
public class E31_DeadlockingDiningPhilosophers {

    public static void main(String[] args) throws InterruptedException {
        int ponder = 5;
        int size = 5;
        ExecutorService exec = Executors.newCachedThreadPool();
        BlockingQueue<Chopstick> queue = new LinkedBlockingQueue<Chopstick>(size);
        for (int i = 0; i < size; i++)
            queue.put(new Chopstick());
        for (int i = 0; i < size; i++)
            exec.execute(new Philosopher(queue, i, ponder));
        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
    }
}

class Chopstick {
    private boolean taken = false;

    public void take() throws InterruptedException {
        while (taken) {
            wait();
        }
        taken = true;
    }


}

class Philosopher implements Runnable {
    BlockingQueue<Chopstick> queue;
    private Chopstick left;
    private Chopstick right;
    private final int id;
    private final int ponderFactor;
    private Random rand = new Random(47);

    public Philosopher(BlockingQueue<Chopstick> queue, int ident, int ponder) {
        this.queue = queue;
        id = ident;
        ponderFactor = ponder;
    }

    private void pause() throws InterruptedException {
        if (ponderFactor == 0) {
            return;
        }
        TimeUnit.MILLISECONDS.sleep(rand.nextInt(ponderFactor * 250));
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                right = queue.take();
                System.out.println(this + " grabbing right" + queue.size());
                left = queue.take();
                System.out.println(this + " grabbing left"+ queue.size());
                pause();
                System.out.println(this + " eating");
                queue.put(right);
                queue.put(left);
            }
        } catch (InterruptedException e) {
            System.out.println(this + " " + "exiting via interrupt");
        }
    }

    @Override
    public String toString() {
        return "Philosopher " + id;
    }
}